package outils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Scanner;

import resultatTest.ResultatTestIPSecCIM;
import resultatTest.ResultatTestIPSecPolicy;
import resultatTest.ResultatTestIPSecRule;
import resultatTest.ResultatTestIPTableCIM;
import resultatTest.ResultatTestIPTableCommande;
import run.Commande;
import run.Executable;
import test.TestCommandeSimple;
import test.TestIPSecCIM;
import test.TestIPSecPolicy;
import test.TestIPSecRule;
import test.TestIPTableCIM;
import test.TestIPTableCommande;

/**
 * 
 */

/**
 * @author alith
 *
 */
public class Parser {
	
	//C'est clairement pas optimisé... D'un point de vue memoire: on met tout dans la memoire haute.
	// mais j'ai pas envie de me prendre la tete avec les iterateurs next...
	// en plus on refait plein de fois les meme parcours...
	// J'essaie par contre de rendre des bouts de code réutilisable au max.
	
	private static String[] indicateurs = {"#cmd","#testIPSecRule","#testIPSecPolicy","#testIPTable","#testIPTableCIM","#testIPSecCIM", "#failed","#passed"};
	
	private static String comment = "#comment";
	
	private static boolean isComment(String ligne) {
		return ligne.trim().startsWith(comment);
	}
	
	public static Collection<Executable> parse (File fichier){
		ArrayList<Executable> listeExecutables = new ArrayList<Executable>();
		try {
			ArrayList<String> listeExec = splitTests(fichier);
			for (String exec : listeExec) {
				switch (getTypeInstruction(exec)) {
					case 0 : {
						listeExecutables.add(getCommande(exec));
					} break;
					//les traitements supplementaires d'ipSec sont faits lors des appels aux constructeurs... :)
					case 1 : {
						listeExecutables.add(new TestIPSecRule(getCommande(exec), new ResultatTestIPSecRule(getResultatAttendu(exec))));
					} break;
					case 2 : {
						listeExecutables.add(new TestIPSecPolicy(getCommande(exec), new ResultatTestIPSecPolicy(getResultatAttendu(exec))));
					} break;
					case 3 : {
						listeExecutables.add(new TestIPTableCommande(getCommande(exec), new ResultatTestIPTableCommande(getResultatAttendu(exec))));
					} break;
					case 4 : {
						listeExecutables.add(new TestIPTableCIM(getCommande(exec), new ResultatTestIPTableCIM(getResultatAttendu(exec))));
					} break;
					case 5 : {
						listeExecutables.add(new TestIPSecCIM(getCommande(exec), new ResultatTestIPSecCIM(getResultatAttendu(exec))));
					} break;
					case 6 : {
						listeExecutables.add(new TestCommandeSimple(getCommande(exec), 1));
					} break;
					case 7 : {
						listeExecutables.add(new TestCommandeSimple(getCommande(exec), 0));
					} break;
					default: {
						System.out.println("Commande inconnue: " + exec);
					} break;
				}
			}
		} catch (Exception e) {
			System.out.print("Erreur dans la lecture du fichier: " ); e.printStackTrace();
			System.exit(1);
		}
		return listeExecutables;
	}
	
	private static ArrayList<String> splitTests(File fichier) throws FileNotFoundException {
		ArrayList<String> tests = new ArrayList<String>();
		Scanner scanner=new Scanner(fichier);		
		int j = 0;
		while (scanner.hasNextLine()) {
		    String ligne = scanner.nextLine();
		    boolean isIndicateur = false;
		    for (int i=0; i<indicateurs.length; i++) {
		    	isIndicateur |= ligne.trim().startsWith(indicateurs[i]);
		    }
		    String aux;
		    if (isIndicateur) {
		    	aux = new String (ligne.trim());
		    	tests.add(aux+"\n");
		    	j++;
		    } else {
		    	if (!isComment(ligne) && !ligne.matches("\b*")) {
		    		aux = tests.get(j-1)+ ligne.trim() + "\n";
		    		tests.set(j-1, aux);
		    	}
		    }
		}
		scanner.close();
		return tests;
	}
	
	private static int getTypeInstruction(String test) {
		String[] ligneSplitee = test.split(" ");
		for (int i = 0; i<indicateurs.length; i++) {
			if (ligneSplitee[0].equalsIgnoreCase(indicateurs[i])) return i; 
		}
		return -1;
	}
	
	private static Commande getCommande(String test) {
		String[] testSplite = test.split("\n");
		String [] ligneSplitee = testSplite[0].split(" ");
		String cmd = "";
		for (int i =1; i< ligneSplitee.length; i++) {
			cmd += ligneSplitee[i] + " ";	
		}
		return new Commande (cmd);		
	}
	
	private static ArrayList<Ligne> getResultatAttendu(String test) {
		ArrayList<Ligne> result = new ArrayList<Ligne>();
		String[] testSplite = test.split("\n");
		for (int j = 1; j<testSplite.length; j++) {
			result.add( new Ligne(testSplite[j]));
		}
		return result;		
	}
	
	/*public static ArrayList<Ligne> getLignes(File fichier) {
		ArrayList<Ligne> lignes = new ArrayList<Ligne>();		
		Scanner scanner;
		try {
			scanner = new Scanner(fichier);
			while (scanner.hasNextLine()) {
			    lignes.add(new Ligne(scanner.nextLine()));
			}
			scanner.close();
		} catch (FileNotFoundException e) {
			System.out.println("impossible de lire le fichier temporaire.");
			e.printStackTrace();
		}
		System.out.println("test: "+ lignes);
		return lignes;
	}*/
	
	public static ArrayList<Ligne> getLignes(InputStream in) {
		ArrayList<Ligne> lignes = new ArrayList<Ligne>();		
		Scanner scanner;
		try {
			scanner = new Scanner(in);
			while (scanner.hasNextLine()) {
				String aux = scanner.nextLine();
				if (!isComment(aux) && !aux.matches("\b*")) lignes.add(new Ligne(aux));
			}
			scanner.close();
		} catch (Exception e) {
			System.out.println("impossible de lire l'entrée fournie.");
			e.printStackTrace();
		}
		return lignes;
	}
}
